# -*- coding: utf-8  -*-
#!/usr/local/bin/python

__author__ = 'yaojian'

import hashlib
from usermanage.account.models import User
from misc.errorcode import ERROR_CODE, ERROR_MESSAGE
from configuration.channels import ChannelConf
from django.db.models import Q
from usermanage.account.models import User
from usermanage.account.models import UserContact, UserContactType

class LittleOrangeOnlineServiceAuthBackend(object):
    """
    UserName/Email/Mobile/Open SNS(weibo,qq,......)/...... Authentication Backend
    """
    def authenticate(self, username = None, password = None):
        if username is not None and password is not None:
            if username.isdigit():
                return self.auth_by_mobile(username, password)
            elif username.find("@") > -1:
                return self.auth_by_email(username, password)
            else:
                return self.auth_by_username(username, password)
        else:
            return None

    def get_user(self, user_id):
        """
        Get a User object from the user_id.
        """
        try:
            return User.objects.get(pk = user_id)
        except User.DoesNotExist:
            return None

    def auth_by_username(self, username = None, password = None):
        """
        Authenticate a user based on user name.
        """
        try:
            user = User.objects.get(Q(username__iexact = username))
            if self._check_password(user, password):
                return user
        except User.DoesNotExist:
            return None

    def auth_by_email(self, email = None, password = None):
        """
         Authenticate a user based on email address as the user name.
        """
        if not email or not password:
            return None

        # the comfirmed or latest one
        qs_usercontact = UserContact.objects.select_related().filter(type = UserContactType.Email, value__iexact = email).order_by("-is_confirmed", "-last_update")[:1]
        if qs_usercontact:
            user = qs_usercontact[0].user
            if self._check_password(user, password):
                return user

        return None

    def auth_by_mobile(self, mobile = None, password = None):
        """
        Authenticate a user based on mobile number as the user name.
        """
        if not mobile or not password:
            return None

        # the comfirmed or latest one
        qs_usercontact = UserContact.objects.select_related().filter(Q(type = UserContactType.Mobile1) \
                                                                    | Q(type = UserContactType.Mobile2) \
                                                                    | Q(type = UserContactType.Mobile3)).filter(value__iexact = mobile).order_by("-is_confirmed", "-last_update")[:1]

        if qs_usercontact:
            user = qs_usercontact[0].user
            if self._check_password(user, password):
                return user

        return None

    def _check_password(self, user, password):
        """
        此处需兼容AMAP的Md5密码, 导航用户密码为明文存储, 导入时密码统一使用SHA1加密存储
        登录成功后自动转换为SHA1统一加密
        """
        if len(user.password) == 32 and user.password == hashlib.md5(password).hexdigest():
            user.set_password(password)
            user.save()
        return user.check_password(password);





def create_user(channel, username, password, **extra_fields):
    if(not channel) or (not username) or (not password):
        return None

    channelobj = ChannelConf.get(channel, 'channel')
    if channel is None:
        return None
    channel_id = channelobj["id"]

    new_user = User.objects.create_user(channel_id, username, password, **extra_fields)
    if new_user:
        new_user.is_staff = False
        new_user.is_superuser = False
        new_user.is_active = True
        new_user.save()
        return new_user
    else:
        return None


def check_username(username):
    try:
        User.objects.get(Q(username__iexact = username))
        return False, ERROR_CODE.USERNAME_ALREADY_EXIST, ERROR_MESSAGE.USERNAME_ALREADY_EXIST
    except User.DoesNotExist:
        return True, ERROR_CODE.SUCCESS, ERROR_MESSAGE.SUCCESS

    else:
        return False, ERROR_CODE.UNKNOWN_ERROR, ERROR_MESSAGE.UNKNOWN_ERROR